package com.free.semantic.core.service.impl;

import com.free.semantic.common.Ls;
import com.free.semantic.common.ParamNode;
import com.free.semantic.common.RangeObj;
import com.free.semantic.common.RelationChain;
import com.free.semantic.core.ConceptInstanceManage;
import com.free.semantic.core.ConceptManage;
import com.free.semantic.core.FunctionProvider;
import com.free.semantic.core.impl.ConceptInstanceManageImpl;
import com.free.semantic.core.impl.ConceptManageImpl;
import com.free.semantic.core.script.SemanticNetEngine;
import com.free.semantic.core.script.impl.ScriptEngineImpl;
import com.free.semantic.core.service.FreeService;
import com.free.semantic.facade.Link;
import com.free.semantic.facade.Node;
import com.free.semantic.req.RelaItemDef;
import com.free.semantic.req.RelationDefineGroup;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.free.semantic.utils.Utils.*;

@Service
public class FreeServiceImpl implements FreeService {

    @Resource
    private FunctionProvider functionProvider;

    private SemanticNetEngine semanticNetEngine = new ScriptEngineImpl();

    private Map<String, ConceptInstanceManage> manageMap = new HashMap<>();

    @PostConstruct
    public void getConcept() {
        ConceptManageImpl conceptManage = new ConceptManageImpl();
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.one("B"));
            conceptManage.addRelationDefine("继承", Ls.of(go));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.more("B"));
            RelaItemDef back = new RelaItemDef(Ls.of(RangeObj.one("B")), RangeObj.one("A"));
            conceptManage.addRelationDefine("包含", Ls.of(go, back));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.more("B"));
            conceptManage.addRelationDefine("单包含", Ls.of(go));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.one("B"));
            conceptManage.addRelationDefine("单找到", Ls.of(go));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A"), RangeObj.one("B")), RangeObj.one("C"));
            conceptManage.addRelationDefine("双找到", Ls.of(go));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.one("B"));
            RelaItemDef back = new RelaItemDef(Ls.of(RangeObj.one("B")), RangeObj.more("A"));
            conceptManage.addRelationDefine("属性", Ls.of(go, back));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.one("B"));
            conceptManage.addRelationDefine("单属性", Ls.of(go));
        }
        {
            RelaItemDef go = new RelaItemDef(Ls.of(RangeObj.one("A")), RangeObj.one("B"));
            RelaItemDef back = new RelaItemDef(Ls.of(RangeObj.one("B")), RangeObj.one("A"));
            conceptManage.addRelationDefine("唯一键", Ls.of(go, back));
        }

        conceptManage.addConcept("用户", "习惯", "习惯记录");

        conceptManage.addConcept("时刻", "时间段", "开始时间", "结束时间");

        conceptManage.addConcept("邮箱", "登录验证码", "token");

        conceptManage.addConcept("完成时间");

        conceptManage.addConcept("习惯名称");

        conceptManage.addConcept("语义网络脚本", "语义网络结构");

        conceptManage.instanceRelation("双找到", new HashMap<String, String>() {
            {
                put("A", "邮箱");
                put("B", "用户");
                put("C", "登录验证码");
            }
        });

        conceptManage.instanceRelation("单找到", new HashMap<String, String>() {
            {
                put("A", "邮箱");
                put("B", "用户");
            }
        });

        conceptManage.instanceRelation("单找到", new HashMap<String, String>() {
            {
                put("A", "语义网络脚本");
                put("B", "语义网络结构");
            }
        });

        conceptManage.instanceRelation("单找到", new HashMap<String, String>() {
            {
                put("A", "习惯");
                put("B", "习惯名称");
            }
        });

        conceptManage.instanceRelation("双找到", new HashMap<String, String>() {
            {
                put("A", "邮箱");
                put("B", "登录验证码");
                put("C", "token");
            }
        });

        conceptManage.instanceRelation("单找到", new HashMap<String, String>() {
            {
                put("A", "token");
                put("B", "用户");
            }
        });

        conceptManage.instanceRelation("单找到", new HashMap<String, String>() {
            {
                put("A", "习惯记录");
                put("B", "完成时间");
            }
        });
        conceptManage.instanceRelation("单找到", new HashMap<String, String>() {
            {
                put("A", "习惯记录");
                put("B", "开始时间");
            }
        });
        conceptManage.instanceRelation("继承", new HashMap<String, String>() {
            {
                put("A", "完成时间");
                put("B", "时刻");
            }
        });

        conceptManage.instanceRelation("继承", new HashMap<String, String>() {
            {
                put("A", "结束时间");
                put("B", "时刻");
            }
        });

        conceptManage.instanceRelation("单包含", new HashMap<String, String>() {
            {
                put("A", "时间段");
                put("B", "时刻");
            }
        });

        conceptManage.instanceRelation("单属性", new HashMap<String, String>() {
            {
                put("A", "时间段");
                put("B", "开始时间");
            }
        });

        conceptManage.instanceRelation("单属性", new HashMap<String, String>() {
            {
                put("A", "时间段");
                put("B", "结束时间");
            }
        });

        conceptManage.instanceRelation("继承", new HashMap<String, String>() {
            {
                put("A", "开始时间");
                put("B", "时刻");
            }
        });

        conceptManage.instanceRelation("包含", new HashMap<String, String>() {
            {
                put("A", "用户");
                put("B", "习惯");
            }
        });

        conceptManage.instanceRelation("包含", new HashMap<String, String>() {
            {
                put("A", "习惯");
                put("B", "习惯记录");
            }
        });

        conceptManage.instanceRelation("唯一键", new HashMap<String, String>() {
            {
                put("A", "用户");
                put("B", "object id");
            }
        });
        conceptManage.instanceRelation("唯一键", new HashMap<String, String>() {
            {
                put("A", "习惯");
                put("B", "object id");
            }
        });
        conceptManage.instanceRelation("唯一键", new HashMap<String, String>() {
            {
                put("A", "习惯记录");
                put("B", "object id");
            }
        });
        ConceptInstanceManageImpl instanceManage = new ConceptInstanceManageImpl(conceptManage, functionProvider);
        manageMap.put("habitModel", instanceManage);
    }

    @PostConstruct
    private void registerInterfaceMode() {
        RelationDefineGroup group = new RelationDefineGroup();
        // relation 包含(A,B)
        defineRelation(group, "包含", defineItem(oneObj("A"), moreObj("B")), // A->B=[0,) //代表 针对任意一个A，都可以找到 [0,)个B与之对应
                defineItem(oneObj("B"), oneObj("A"))); // B->A=1 //代表 针对任意一个B，都可以找到 1个A与之对应

        // 使用包含关系 定义一个语义网络
        ConceptManage model = getConceptManage(group);
        // object 省份 城市
        object(model, "省份", "城市");
        // 包含(省份,城市)
        createRelation(model, "包含", "省份", "城市");
        // 创建模型的一个实现，并且实现 省份查询城市 和 城市查询 省份 函数（添加一些测试数据）
        ConceptInstanceManage modelInstance = new ConceptInstanceManageImpl(model);
        manageMap.put("interfaceModel", modelInstance);
    }

    @PostConstruct
    private void registerTestMode() {
        RelationDefineGroup group = new RelationDefineGroup();
        // relation 包含(A,B)
        defineRelation(group, "包含", defineItem(oneObj("A"), moreObj("B")), // A->B=[0,) //代表 针对任意一个A，都可以找到 [0,)个B与之对应
                defineItem(oneObj("B"), oneObj("A"))); // B->A=1 //代表 针对任意一个B，都可以找到 1个A与之对应

        // 使用包含关系 定义一个语义网络
        ConceptManage model = getConceptManage(group);
        // object 省份 城市
        object(model, "省份1", "城市1");
        // 包含(省份,城市)
        createRelation(model, "包含", "省份1", "城市1");

        // 创建模型的一个实现，并且实现 省份查询城市 和 城市查询 省份 函数（添加一些测试数据）
        ConceptInstanceManage modelInstance = new ConceptInstanceManageImpl(model, buildMap("省份1", "城市1",
                new String[][]{{"浙江", "杭州"}, {"浙江", "金华"}, {"山西", "长治"}, {"山西", "运城"}, {"广东", "广州"}, {"广东", "珠海"}}));
        manageMap.put("testModel", modelInstance);
    }

    @Override
    public List<Object> takePath(String conceptName, List<ParamNode> from, String destObject) {
        return manageMap.get(conceptName).takePath(from, destObject);
    }

    @Override
    public Object execScript(String conceptName, String script) {
        return semanticNetEngine.execScript(manageMap.get(conceptName), script);
    }

    @Override
    public Object build(String conceptName, String script) {
        ConceptManage conceptM = new ConceptManageImpl();
        ConceptInstanceManage instanceManage = new ConceptInstanceManageImpl(conceptM);
        manageMap.put(conceptName, instanceManage);
        ConceptInstanceManage manage = manageMap.get(conceptName);
        try {
            return semanticNetEngine.execScript(manage, script);
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    @Override
    public ConceptInstanceManage get(String concept) {
        return manageMap.get(concept);
    }

    @Override
    public void set(String concept, ConceptInstanceManage instanceManage) {
        manageMap.put(concept, instanceManage);
    }

    @Override
    public List<RelationChain> searchPath(String conceptName, List<String> from, String destObject) {
        ConceptInstanceManage instanceManage = manageMap.get(conceptName);
        return instanceManage.concept().findAllRelationChain(from, destObject);
    }

    @Override
    public List<Node> getAllNode(String concept) {
        return manageMap.get(concept).concept().getAllNode();
    }

    @Override
    public List<Link> getAllLink(String concept) {
        return manageMap.get(concept).concept().getAllLink();

    }

}
